#pragma once

#include <cstddef>

/**
 * @brief 第六版本：新增 release 功能。
 *
 * release 用于“放弃所有权”而不删除对象，调用者需手动 delete。
 * 典型场景：与库函数交互，需要手动管理生命周期时使用。
 */
template <typename T, typename Deleter = void(*)(T*)>
class UniquePtr {
public:
    using pointer      = T*;
    using element_type = T;
    using deleter_type = Deleter;

    static void default_delete(T* ptr) noexcept {
        delete ptr;
    }

    constexpr UniquePtr() noexcept
        : ptr_(nullptr)
        , deleter_(default_delete) {}

    constexpr UniquePtr(std::nullptr_t) noexcept
        : UniquePtr() {}

    explicit UniquePtr(pointer ptr) noexcept
        : ptr_(ptr)
        , deleter_(default_delete) {}

    ~UniquePtr() {
        reset();
    }

    void reset(pointer ptr = nullptr) noexcept {
        if (ptr_) {
            deleter_(ptr_);
        }
        ptr_ = ptr;
    }

    /**
     * @brief 放弃所有权但不删除对象。
     *
     * @return 原始指针（调用者负责后续 delete）。
     *         内部指针被置空，UniquePtr 后续不再管理该资源。
     */
    pointer release() noexcept {
        pointer raw = ptr_;
        ptr_ = nullptr;
        return raw;
    }

    pointer get() const noexcept {
        return ptr_;
    }

    element_type& operator*() const noexcept {
        return *ptr_;
    }

    pointer operator->() const noexcept {
        return ptr_;
    }

    explicit operator bool() const noexcept {
        return ptr_ != nullptr;
    }

private:
    pointer      ptr_;
    deleter_type deleter_;
};